package com.example.ecs.systems.physics;

import com.example.ecs.components.PositionComponent;
import com.example.ecs.components.VelocityComponent;
import com.example.ecs.components.physics.SATCollisionComponent;
import com.example.ecs.core.Entity;
import com.example.ecs.core.System;

/**
 * SATCollisionSystem类负责处理实体之间的SAT碰撞检测
 */
public class SATCollisionSystem extends System {
    @Override
    public void update(double deltaTime) {
        // 检查所有实体对之间的碰撞
        for (int i = 0; i < entities.size(); i++) {
            for (int j = i + 1; j < entities.size(); j++) {
                Entity entityA = entities.get(i);
                Entity entityB = entities.get(j);
                
                if (entityA.hasComponent(PositionComponent.class) &&
                    entityA.hasComponent(SATCollisionComponent.class) &&
                    entityB.hasComponent(PositionComponent.class) && 
                    entityB.hasComponent(SATCollisionComponent.class)) {
                    
                    // 检查SAT碰撞
                    if (checkSATCollision(entityA, entityB)) {
                        // 处理碰撞响应
                        handleCollision(entityA, entityB);
                    }
                }
            }
        }
    }
    
    /**
     * 使用SAT算法检查两个实体是否发生碰撞
     */
    private boolean checkSATCollision(Entity entityA, Entity entityB) {
        PositionComponent posA = entityA.getComponent(PositionComponent.class);
        PositionComponent posB = entityB.getComponent(PositionComponent.class);
        SATCollisionComponent satA = entityA.getComponent(SATCollisionComponent.class);
        SATCollisionComponent satB = entityB.getComponent(SATCollisionComponent.class);
        
        // 获取多边形顶点并应用位置偏移
        double[][] verticesA = new double[satA.vertices.length][2];
        double[][] verticesB = new double[satB.vertices.length][2];
        
        for (int i = 0; i < satA.vertices.length; i++) {
            verticesA[i][0] = satA.vertices[i][0] + posA.x;
            verticesA[i][1] = satA.vertices[i][1] + posA.y;
        }
        
        for (int i = 0; i < satB.vertices.length; i++) {
            verticesB[i][0] = satB.vertices[i][0] + posB.x;
            verticesB[i][1] = satB.vertices[i][1] + posB.y;
        }
        
        // 获取所有边的法向量作为投影轴
        double[][] edgesA = getEdges(verticesA);
        double[][] edgesB = getEdges(verticesB);
        
        // 检查多边形A的边法向量
        for (double[] edge : edgesA) {
            double[] axis = {-edge[1], edge[0]}; // 法向量
            normalize(axis);
            
            // 投影两个多边形到轴上
            double[] projectionA = projectPolygon(verticesA, axis);
            double[] projectionB = projectPolygon(verticesB, axis);
            
            // 检查投影是否重叠
            if (!overlap(projectionA, projectionB)) {
                return false; // 分离轴找到，不相交
            }
        }
        
        // 检查多边形B的边法向量
        for (double[] edge : edgesB) {
            double[] axis = {-edge[1], edge[0]}; // 法向量
            normalize(axis);
            
            // 投影两个多边形到轴上
            double[] projectionA = projectPolygon(verticesA, axis);
            double[] projectionB = projectPolygon(verticesB, axis);
            
            // 检查投影是否重叠
            if (!overlap(projectionA, projectionB)) {
                return false; // 分离轴找到，不相交
            }
        }
        
        return true; // 所有轴都重叠，相交
    }
    
    /**
     * 获取多边形的边向量
     */
    private double[][] getEdges(double[][] vertices) {
        int numVertices = vertices.length;
        double[][] edges = new double[numVertices][2];
        
        for (int i = 0; i < numVertices; i++) {
            int next = (i + 1) % numVertices;
            edges[i][0] = vertices[next][0] - vertices[i][0];
            edges[i][1] = vertices[next][1] - vertices[i][1];
        }
        
        return edges;
    }
    
    /**
     * 标准化向量
     */
    private void normalize(double[] vector) {
        double length = Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1]);
        if (length > 0) {
            vector[0] /= length;
            vector[1] /= length;
        }
    }
    
    /**
     * 将多边形投影到轴上
     */
    private double[] projectPolygon(double[][] vertices, double[] axis) {
        double min = dotProduct(vertices[0], axis);
        double max = min;
        
        for (int i = 1; i < vertices.length; i++) {
            double projection = dotProduct(vertices[i], axis);
            if (projection < min) {
                min = projection;
            } else if (projection > max) {
                max = projection;
            }
        }
        
        return new double[]{min, max};
    }
    
    /**
     * 计算两个向量的点积
     */
    private double dotProduct(double[] a, double[] b) {
        return a[0] * b[0] + a[1] * b[1];
    }
    
    /**
     * 检查两个投影区间是否重叠
     */
    private boolean overlap(double[] a, double[] b) {
        return a[1] >= b[0] && b[1] >= a[0];
    }
    
    /**
     * 处理两个实体之间的碰撞
     */
    private void handleCollision(Entity entityA, Entity entityB) {
        // 如果两个实体都是固体，则简单地分离它们
        if (entityA.getComponent(SATCollisionComponent.class).solid && 
            entityB.getComponent(SATCollisionComponent.class).solid) {
            
            PositionComponent posA = entityA.getComponent(PositionComponent.class);
            PositionComponent posB = entityB.getComponent(PositionComponent.class);
            VelocityComponent velA = entityA.getComponent(VelocityComponent.class);
            VelocityComponent velB = entityB.getComponent(VelocityComponent.class);
            
            // 简单的碰撞响应：交换速度
            if (velA != null && velB != null) {
                double tempVx = velA.vx;
                double tempVy = velA.vy;
                velA.vx = velB.vx;
                velA.vy = velB.vy;
                velB.vx = tempVx;
                velB.vy = tempVy;
            }
        }
    }
}